package com.zq;

import java.util.Arrays;
import java.util.List;

/**
 * 方法引用 −
 * 方法引用可以直接引用已有Java类或对象（实例）的方法或构造器。与lambda联合使用，方法引用可以使语言的构造更紧凑简洁，减少冗余代码。
 * 方法引用通过方法的名字来指向一个方法。
 * 方法引用可以使语言的构造更紧凑简洁，减少冗余代码。
 * 方法引用使用一对冒号 :: 。
 */
public class MethodReferenceDemo {

    @FunctionalInterface
    public interface Fun<T> {
        T get();
    }

    public static MethodReferenceDemo create(Fun<MethodReferenceDemo> fun) {
        return fun.get();
    }

    public static void collide(MethodReferenceDemo collided) {

        System.out.println("Collided " + collided.toString());
    }

    public void follow(final MethodReferenceDemo another) {
        System.out.println("Following the " + another.toString());
    }

    public void repair() {
        System.out.println("Repaired " + this.toString());
    }

    public void test(String str) {
        System.out.println("test " + str);
    }

    public static void main(String[] args) {
        List<MethodReferenceDemo> list =  Arrays.asList(new MethodReferenceDemo(),new MethodReferenceDemo(),new MethodReferenceDemo());
        new MethodReferenceDemo().test2(list);
        new MethodReferenceDemo().test3(list);
        new MethodReferenceDemo().test4(list);

    }

    /**
     * 1.构造器引用,它的语法是Class::new，或者更一般的Class< T >::new实例如下：
     *   我们使用lambda表达式来的话可以写成下面这样
     *   Fun<MethodReference> fun=()-> new MethodReference();
     *   MethodReference mr=MethodReference.create(fun);
     *   但我们可以根据简化，它的语法是Class::new，或者更一般的Class< T >::new实例如下：
     */
    public void test1() {
        // jdk 1.8 之前写法，匿名内部类
        MethodReferenceDemo methodReferenceDemo1 = MethodReferenceDemo.create(new Fun<MethodReferenceDemo>() {
            @Override
            public MethodReferenceDemo get() {
                return new MethodReferenceDemo();
            }
        });
        //lambda 写法
        MethodReferenceDemo methodReferenceDemo2 = MethodReferenceDemo.create(() -> {
            return new MethodReferenceDemo();
        });
        // MethodReference methodReference
        //方法引用写法，进一步简化代码
        MethodReferenceDemo methodReferenceDemo3 = MethodReferenceDemo.create(MethodReferenceDemo::new);

    }

    /**
     * 2.静态方法引用：它的语法是Class::static_method实例如下：
     */
    public void test2(List<MethodReferenceDemo> list){
        list.forEach(MethodReferenceDemo::collide);
    }

    /**
     * 3.对象方法引用(特定类的任意对象的方法引用)：
     * 若Lambda参数列表中的第一个参数是实例方法的参数调用者，而第二个参数是实例方法的参数时，可以使用对象方法引用。
     * 它的语法是Class::method实例如下：
     */
    public void test3(List<MethodReferenceDemo> list){
        list.forEach(MethodReferenceDemo::repair);
    }

    /**
     * 4.实例方法引用(特定对象的方法引用)：它的语法是 instance::method实例如下：
     */
    public void test4(List<MethodReferenceDemo> list){
        MethodReferenceDemo mr = MethodReferenceDemo.create(MethodReferenceDemo::new);
        list.forEach(mr::follow);
    }








}
